//
//  NetworkingManager.m
//  YiJuZhangShou
//
//  Created by 冷悦 on 16/3/3.
//  Copyright © 2016年 Uranus. All rights reserved.
//

#import "NetworkingBaseManager.h"
#import "CoreDataUtil.h"
#import "SyncTimer.h"
#import "YiJuApiMapping.h"

typedef void(^SuccessBlock)(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject);
typedef void(^FailureBlock)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error);

@interface NetworkingBaseManager()

@property (nonatomic, strong)NSString *requestId;

@property (nonatomic, strong)NSDictionary *responseParams;

@property (nonatomic, copy)SuccessBlock successBlock;

@property (nonatomic, copy)FailureBlock failureBlock;

@property (nonatomic, strong)NSMutableArray *requestIds;

@end

@implementation NetworkingBaseManager

#pragma mark - Initialize
- (instancetype)init{
    if (self = [super init]) {
        _manger = [AFHTTPSessionManager manager];
    }
    return self;
}

#pragma mark - Override
- (void)dealloc{
    for (NSString *requestId in self.requestIds) {
        [[RequestGenerator sharedInstance] deleteProcessingRequest:requestId];
    }
}

- (BOOL)validResponseData:(NSDictionary *)responseParams{
    if (self.validator != nil && [self.validator respondsToSelector:@selector(isCorrectWithCallbackData:)]) {
        return [self.validator isCorrectWithCallbackData:responseParams];
    } else {
        return YES;
    }
}

- (BOOL)validRequestData:(NSDictionary *)requestParams{
    if (self.validator != nil && [self.validator respondsToSelector:@selector(isCorrectWithParamsData:)]) {
        return [self.validator isCorrectWithParamsData:requestParams];
    } else {
        return YES;
    }
}

- (void)executeSuccessWithdParams:(NSDictionary *)params{
    if (self.successDelegate != nil && [self.successDelegate respondsToSelector:@selector(manager:callAPIDidSuccessWithParams:)]) {
        [self.successDelegate manager:self callAPIDidSuccessWithParams:params];
    }
}

- (void)executeError:(NSDictionary *)responseParams{
    if (self.failureDelegate != nil && [self.failureDelegate respondsToSelector:@selector(manager:callAPIDidError:)]) {
        [self.failureDelegate manager:self callAPIDidError:responseParams];
    }
}

- (void)executeFailure:(NSError *)error andTask:(NSURLSessionDataTask *)task{
    if (self.failureBlock != nil && [self.failureDelegate respondsToSelector:@selector(manager:callAPIDidFailed:andTask:)]) {
        [self.failureDelegate manager:self callAPIDidFailed:error andTask:task];
    }
}

- (void)executeBeforeSuccess:(NSURLSessionDataTask *) task withResponse:(NSDictionary *)responseParams{
    if (self.interceptor != nil && [self.interceptor respondsToSelector:@selector(beforePerformSuccess:withResponse:)]) {
        [self.interceptor beforePerformSuccess:task withResponse:responseParams];
    }
}

- (void)executeAfterSuccess:(NSDictionary *)responseParams{
    if (self.interceptor != nil && [self.interceptor respondsToSelector:@selector(manager:afterPerformSuccessWithResponse:)]) {
        [self.interceptor manager:self afterPerformSuccessWithResponse:responseParams];
    }
}

- (void)executeBeforeFailWithResponse:(NSError *)error{
    if (self.interceptor != nil && [self.interceptor respondsToSelector:@selector(manager:beforePerformFailWithResponse:)]) {
        [self.interceptor manager:self beforePerformFailWithResponse:error];
    }
}

- (void)executeAfterFailWithResponse:(NSError *)error{
    if (self.interceptor != nil && [self.interceptor respondsToSelector:@selector(manager:afterPerformFailWithResponse:)]) {
        [self.interceptor manager:self afterPerformFailWithResponse:error];
    }
}

- (void)executeShouldCallAPIWithManager{
    if (self.interceptor != nil && [self.interceptor respondsToSelector:@selector(shouldCallAPIWithManager:)]) {
        [self.interceptor shouldCallAPIWithManager:self];
    }
}

- (void)executeAfterCallAPIWithManager{
    if (self.interceptor != nil && [self.interceptor respondsToSelector:@selector(afterCallingAPIWithManager:)]) {
        [self.interceptor afterCallingAPIWithManager:self];
    }
}



- (void)addRequestId{
    NSString *requestId = [[RequestGenerator sharedInstance] generateRequestId:self.params
                                                                   requestType:self.requestType
                                                                    andAPIName:self.apiName];
    if ([self.requestIds containsObject:requestId] == NO) {
        [self.requestIds addObject:requestId];
    }
}

- (void)setupLoadGet{
    //设置请求头的http一些默认设置(如果在这之前有一些请求头设置，会被下面内容覆盖)
    self.manger.requestSerializer = [AFHTTPRequestSerializer serializer];
}

- (void)setupLoadPost{
    //设置请求头的json一些默认设置(如果在这之前有一些请求头设置，会被下面内容覆盖)
    self.manger.requestSerializer = [AFJSONRequestSerializer serializer];
}

- (void)setupLoadDelete{
    //设置请求头的http一些默认设置(如果在这之前有一些请求头设置，会被下面内容覆盖)
    self.manger.requestSerializer = [AFHTTPRequestSerializer serializer];
}

- (void)setupLoadPut{
    //设置请求头的json一些默认设置(如果在这之前有一些请求头设置，会被下面内容覆盖)
    self.manger.requestSerializer = [AFJSONRequestSerializer serializer];
}

#pragma mark - Public
- (void)loadRequest{
    //记录本次网络请求操作的标示码(避免规定时间内重复发送相同请求的无谓操作)
    [self addRequestId];
    DDLogInfo(@"发送的地址：%@",self.apiName);
    DDLogInfo(@"发送的参数：%@",[self.params description]);
    switch (self.requestType) {
        case HTTP_PUT:
            [self setupLoadPut];
            [self executeShouldCallAPIWithManager];
            [self.manger PUT:self.apiName
                  parameters:self.params
                     success:self.successBlock
                     failure:self.failureBlock];
            break;
        case HTTP_GET:
            [self setupLoadGet];
            [self executeShouldCallAPIWithManager];
            [self.manger GET:self.apiName
                  parameters:self.params
                    progress:nil
                     success:self.successBlock
                     failure:self.failureBlock];
            break;
        case HTTP_DELETE:
            [self setupLoadDelete];
            [self executeShouldCallAPIWithManager];
            [self.manger DELETE:self.apiName
                     parameters:self.params
                        success:self.successBlock
                        failure:self.failureBlock];
            break;
        case HTTP_POST:
            [self setupLoadPost];
            [self executeShouldCallAPIWithManager];
            DDLogInfo(@"地址：%@,发送参数：%@",self.apiName,self.params);
            [self.manger POST:self.apiName
                   parameters:self.params
                     progress:nil
                      success:self.successBlock
                      failure:self.failureBlock];
            break;
        case HTTP_UPLOAD:{
            [self setupLoadPost];
            [self executeShouldCallAPIWithManager];
            [self.manger POST:self.apiName parameters:self.params constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
                NSString *name = _avatarFileName == nil?AvatarFileKeyName:_avatarFileName;
                if (_postImage == nil) {
                    DDLogWarn(@"未设置需上传的图片");
                    return ;
                }
                [formData appendPartWithFileData:UIImageJPEGRepresentation(_postImage, 1.0) name:name fileName:name mimeType:@"image/jpeg"];
            } progress:nil success:self.successBlock failure:self.failureBlock];
            break;
        }
        default:
            NSAssert(NO, @"未设置Http请求类型（GET,POST,PUT,DELETE）");
            break;
    }
    //发送网络请求后，记录本次网络请求操作
    [self executeAfterCallAPIWithManager];
}



#pragma mark - Getters
- (NSMutableArray *)requestIds{
    if (_requestIds == nil) {
        _requestIds = [NSMutableArray array];
    }
    
    return _requestIds;
}

- (SuccessBlock)successBlock{
    //成功指正确发送网络请求，并成功返回数据（无关数据在服务器数据库是否正确匹配）
    if (_successBlock == nil) {
        __weak typeof(self) weakSelf = self;
        _successBlock = ^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            DDLogInfo(@"地址：%@,最初返回数据：%@, and task is %@",weakSelf.apiName,[responseObject description], task);
            //验证成功返回数据格式是否正确
            BOOL isValid = [weakSelf validResponseData:responseObject];
            
            if (isValid) {
                //返回数据格式正确（本次请求正确），准备处理网络数据
                //处理数据前(解token（如果需要）)
                [weakSelf executeBeforeSuccess:task withResponse:responseObject];
                //处理数据（更新UI）
                [weakSelf executeSuccessWithdParams:responseObject];
            } else {
                //返回数据格式错误（本次请求有错误，服务器未能返回正确数据（错误如：数据库没有能匹配的id项数据））
                //处理服务器返回的相关错误信息
                [weakSelf executeError:responseObject];
            }
            //网络请求成功返回数据并且被成功处理返回数据后调用（主要是删除之前缓存的本次请求标示码）
            [weakSelf executeAfterSuccess:responseObject];
        };
    }
    
    return _successBlock;
}

- (FailureBlock)failureBlock{
    //发送网络请求异常失败，中断处理（如服务器异常崩溃连接不上，本地网络变化无网而连接不上）
    if (_failureBlock == nil) {
        __weak typeof(self) weakSelf = self;
        _failureBlock = ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            //处理网络请求异常失败之前
            [weakSelf executeBeforeFailWithResponse:error];
            //处理网络请求异常
            [weakSelf executeFailure:error andTask:task];
            //处理网络请求异常失败之后(主要清除本次请求缓存id用)
            [weakSelf executeAfterFailWithResponse:error];
        };
    }
    
    return _failureBlock;
}


@end
